#include "localtargetadapter.h"

LocalTargetAdapter::LocalTargetAdapter(QString sourcePath, QString targetPath, QString diffPath)
{
    this->sourcePath = sourcePath;
    this->targetPath = targetPath;
    this->diffPath = diffPath;
}

QHash<QString, FileInfo> LocalTargetAdapter::createFileTable(bool calculateHashes)
{
    QHash<QString, FileInfo> table;
    QCryptographicHash hash(QCryptographicHash::Sha1);

    QDirIterator it(sourcePath,
                    QDir::Readable | QDir::Files | QDir::NoDotAndDotDot,
                    QDirIterator::Subdirectories );
    while ( it.hasNext() )
    {
        it.next();

        QString relativePath = it.fileInfo().canonicalFilePath();
        relativePath = relativePath.remove(0, sourcePath.length()+1);
        if(calculateHashes)
        {
            QFile file(it.fileInfo().canonicalFilePath());
            file.open(QFile::ReadOnly);
            while(!file.atEnd())
            {
                hash.addData(file.read(100000000));
            }
            file.close();
            table.insert(relativePath, FileInfo(it.fileInfo().baseName(), QString(hash.result().toHex()), it.fileInfo().size()));
            hash.reset();
        }
        else
        {
            table.insert(relativePath, FileInfo(it.fileInfo().baseName(), "", it.fileInfo().size()));
        }
    }

    QDir dir;
    dir.mkpath(targetPath);
    QFile file(targetPath + ".b");
    if (!file.open(QIODevice::WriteOnly)) {
        qDebug() << "Failed to open file " << targetPath << "for write";
    }

    QDataStream out(&file);
    out << table;

    file.close();

    return table;
}

QHash<QString, FileInfo> LocalTargetAdapter::loadFileTable(bool oldTable)
{
    QHash<QString, FileInfo> table;
    QFile file;
    //FIXME
    if(oldTable) {
        file.setFileName(sourcePath + ".b");
    } else {
        file.setFileName(diffPath + ".b");
    }
    if (!file.open(QIODevice::ReadOnly))
        qDebug() << "Failed to open file "  << sourcePath + ".b" << "for reading";

    QDataStream in(&file);
    in >> table;

    file.close();

    return table;
}

void LocalTargetAdapter::backupFile(QString fileName)
{
    QDir dir;
    dir.mkpath(QFileInfo(targetPath+"/"+fileName).absolutePath());

    FileUtils::copyOverwrite(sourcePath+"/"+fileName, targetPath+"/"+fileName);
//    qDebug() << "Copying " << sourcePath+"/"+fileName <<
//                " to " << targetPath+"/"+fileName;
}

void LocalTargetAdapter::restoreFile(QString fileName)
{
    QDir dir;
    dir.mkpath(QFileInfo(targetPath+"/"+fileName).absolutePath());

    FileUtils::copyOverwrite(sourcePath+"/"+fileName, targetPath+"/"+fileName);
//    qDebug() << "Copying " << sourcePath+"/"+fileName <<
//                " to " << targetPath+"/"+fileName;
}

void LocalTargetAdapter::createDiff(QString fileName)
{
    QDir dir;
    dir.mkpath(QFileInfo(targetPath+"/"+fileName).absolutePath());
    XDeltaWrapper::encode(diffPath+"/"+fileName, sourcePath+"/"+fileName, targetPath+"/"+fileName);
//    qDebug() << "Creating diff... currentFile: " << sourcePath+"/"+fileName <<
//                " oldFile: " << diffPath+"/"+fileName <<
//                " targetFile: " << targetPath+"/"+fileName;
}

void LocalTargetAdapter::restoreDiff(QString fileName)
{
    XDeltaWrapper::decode(sourcePath+"/"+fileName, diffPath+"/"+fileName, targetPath+"/"+fileName);
    qDebug() << "Restoring diff... oldFile: " << diffPath+"/"+fileName <<
                " diffFile: " << sourcePath+"/"+fileName <<
                " targetFile: " << targetPath+"/"+fileName;
}

void LocalTargetAdapter::finalize()
{
}

QDirIterator *LocalTargetAdapter::getFilesInSource()
{
    QDirIterator *it = new QDirIterator(sourcePath,
                                        QDir::Readable | QDir::Files | QDir::NoDotAndDotDot,
                                        QDirIterator::Subdirectories );
    return it;
}

QString LocalTargetAdapter::getSourcePath()
{
    return this->sourcePath;
}

QString LocalTargetAdapter::getTargetPath()
{
    return this->targetPath;
}

quint64 LocalTargetAdapter::getDirSize(QHash<QString, FileInfo> table)
{
    quint64 size = 0;
    foreach(QString key, table.keys())
    {
        size += table.value(key).size;
    }
    return size;
}

quint64 LocalTargetAdapter::getDirSize(QDirIterator *it)
{
    QDirIterator it_copy(it->path(),
                         QDir::Readable | QDir::Files | QDir::NoDotAndDotDot,
                         QDirIterator::Subdirectories );
    quint64 size = 0;
    while(it_copy.hasNext())
    {
        it_copy.next();
        size += it_copy.fileInfo().size();
    }
    return size;
}
